package com.graph;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class Graph {

	private List<Vertex> vertices;
	
	private List<Edge> edges;
	
	private HashMap<String, List<String>> labelToAttrs;
	
	public Graph(HashMap<String, List<String>> labelToAttrs, HashMap<String[], String[]> references) {
		this.labelToAttrs = labelToAttrs;
		vertices = new ArrayList<Vertex>();
		edges = new ArrayList<Edge>();
		
		// Initialize vertices
		int vertexId = 1;
		for (String label : labelToAttrs.keySet()) {
			vertices.add(new Vertex(vertexId, label, labelToAttrs.get(label)));
			vertexId++;
		}
		
		// Initialize Edges
		for (String[] kv : references.keySet()) {
			if (references.get(kv).length == 2) {
				Vertex src = getVertexByLabel(kv[0]);
				Vertex dst = getVertexByLabel(references.get(kv)[0]);
				edges.add(new Edge(src, dst, kv[1], references.get(kv)[1]));
			}
		}
	}
	
	public Graph(HashMap<String, List<String>> labelToAttrs, List<Edge> edges) {
		this.labelToAttrs = labelToAttrs;
		this.edges = edges;
		
		vertices = new ArrayList<Vertex>();
		for (Edge e : edges) {
			if (getVertexByLabel(e.getSrc().getLabel()) == null) {
				vertices.add(e.getSrc());
			}
			if (getVertexByLabel(e.getDst().getLabel()) == null) {
				vertices.add(e.getDst());
			}
		}
	}
	
	public List<Vertex> getVertices() {
		return vertices;
	}
	
	public Vertex getVertexByLabel(String label) {
		for (Vertex v : vertices) {
			if (v.getLabel().equals(label)) {
				return v;
			}
		}
		return null;
	}
	
	public List<Vertex> getNeighbors(Vertex src) {
		List<Vertex> neighbors = new ArrayList<Vertex>();
		for(Edge e : this.getEdgesBySrc(src)) {
			neighbors.add(e.getDst());
		}
		return neighbors;
	}
	
	public void removeVertex(Vertex v) {
		vertices.remove(v);
		List<Edge> es = this.getEdgesBySrc(v);
		List<Edge> ed = this.getEdgesByDst(v);
		edges.removeAll(es);
		edges.removeAll(ed);
	}
	
	public List<Edge> getEdges() {
		return edges;
	}
	
	public List<Edge> getEdgesBySrc(Vertex src) {
		List<Edge> results = new ArrayList<Edge>();
		for (Edge e : edges) {
			if (e.getSrc() == src) {
				results.add(e);
			}
		}
		return results;
	}
	
	public List<Edge> getEdgesByDst(Vertex dst) {
		List<Edge> results = new ArrayList<Edge>();
		for (Edge e : edges) {
			if (e.getDst() == dst) {
				results.add(e);
			}
		}
		return results;
	}
	
	public boolean hasEdge() {
		return !edges.isEmpty();
	}
	
	public HashMap<String, List<String>> getLabelToAttrs() {
		return labelToAttrs;
	}
	
	public int getDegree(Vertex v) {
		return this.getEdgesBySrc(v).size();
	}

	@Override
	public String toString() {
		String out = "[Graph]\n";
		for (Vertex v : vertices) {
			out += v.toString();
		}
		for (Edge e : edges) {
			out += e.toString();
		}
		return out;
	}
	
	
}
